package com.cal.utms.dao.payment;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;

import com.cal.utms.dto.payment.PaymentRequestDto;
import com.cal.utms.entity.MoneyTransaction;
import com.cal.utms.entity.Payment;
import com.cal.utms.entity.PaymentReceiptView;
import com.cal.utms.logAudit.AuditLogInterceptor;
import com.cal.utms.util.HibernateUtil;

public class PaymentDaoImpl implements PaymentDao {

	@SuppressWarnings("unchecked")
	@Override
	public List<PaymentRequestDto> getAvilabelPayments(Date date, int fund_id) {
		Session session = HibernateUtil.getSession().openSession();
		List<PaymentRequestDto> transactions = new ArrayList<PaymentRequestDto>();
		try {
			Criteria criteria = session.createCriteria(PaymentReceiptView.class);
			criteria.add(Restrictions.eq("relatedFundId", fund_id));
			criteria.add(Restrictions.le("affectDate", date));
			criteria.setProjection(Projections.projectionList().add(Projections.property("customerType"), "cusType").add(Projections.property("tranTo"), "customerCode")
					.add(Projections.sum("amont"), "tranAmont").add(Projections.property("relatedFundId"), "fundId").add(Projections.groupProperty("customerType"))
					.add(Projections.groupProperty("tranTo")));
			criteria.setResultTransformer(Transformers.aliasToBean(PaymentRequestDto.class));
			transactions = (List<PaymentRequestDto>) criteria.list();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			session.close();
		}
		return transactions;
	}

	public Object savePayments(List<Payment> payments) {
		Object object = null;
		AuditLogInterceptor interceptor = new AuditLogInterceptor();
		Session session = HibernateUtil.getSession().openSession(interceptor);
		interceptor.setSession(session);
		Transaction tr = null;
		try {
			tr = session.beginTransaction();
			for (Payment payment : payments) {
				object = session.save(payment);
			}
			tr.commit();
		} catch (Exception e) {
			tr.rollback();
			e.printStackTrace();
			object = new Object();
		} finally {
			session.close();
		}
		return object;

	}

	@Override
	public BigDecimal getTotalPayAmoutByCustomer(int customerId, String customerType, int fundId) {
		Session session = HibernateUtil.getSession().openSession();
		BigDecimal totalPayment = BigDecimal.ZERO;
		try {
			totalPayment = (BigDecimal) session
					.createQuery(
							"select sum(P.amount) from Payment P where P.customerType=:cusType and P.customerId=:cusId and P.fund.id=:fundId and P.status=0 GROUP BY P.customerId")
					.setParameter("cusType", customerType).setParameter("cusId", customerId).setParameter("fundId", fundId).uniqueResult();
			if (totalPayment == null) {
				totalPayment = BigDecimal.ZERO;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			session.close();
		}
		return totalPayment;
	}

	@SuppressWarnings("unchecked")
	public List<Payment> getPayments() {
		Session session = HibernateUtil.getSession().openSession();
		List<Payment> payments = new ArrayList<Payment>();
		try {
			payments = session.createQuery("from Payment P where P.status=0").list();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			session.close();
		}
		return payments;
	}

	public Payment getPaymentById(int payment_id) {
		Session session = HibernateUtil.getSession().openSession();
		Payment payment = null;
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			payment = (Payment) session.get(Payment.class, payment_id);
			transaction.commit();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return payment;
	}

	public void confirmPayment(Payment payment, List<MoneyTransaction> moneyTransactions) {
		AuditLogInterceptor interceptor = new AuditLogInterceptor();
		Session session = HibernateUtil.getSession().openSession(interceptor);
		interceptor.setSession(session);
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			session.merge(payment);
			for (MoneyTransaction moneyTransaction : moneyTransactions) {
				session.save(moneyTransaction);
			}
			tx.commit();
		} catch (Exception e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}

	}

	@SuppressWarnings("unchecked")
	public List<PaymentRequestDto> getAvilabelReceipt(Date affectDate, int fund_id) {

		Session session = HibernateUtil.getSession().openSession();
		List<PaymentRequestDto> transactions = new ArrayList<PaymentRequestDto>();
		try {
			Criteria criteria = session.createCriteria(PaymentReceiptView.class);
			criteria.add(Restrictions.eq("relatedFundId", fund_id));
			criteria.add(Restrictions.le("affectDate", affectDate));
			criteria.setProjection(Projections.projectionList().add(Projections.property("customerType"), "cusType").add(Projections.property("tranTo"), "customerCode")
					.add(Projections.sum("amont"), "tranAmont").add(Projections.property("relatedFundId"), "fundId").add(Projections.groupProperty("tranTo")));
			criteria.setResultTransformer(Transformers.aliasToBean(PaymentRequestDto.class));
			transactions = (List<PaymentRequestDto>) criteria.list();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			session.close();
		}
		return transactions;
	}

	public void rejectPayment(Payment payment, List<MoneyTransaction> moneyTransactions) {
		AuditLogInterceptor interceptor = new AuditLogInterceptor();
		Session session = HibernateUtil.getSession().openSession(interceptor);
		interceptor.setSession(session);
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			session.merge(payment);
			if (moneyTransactions != null) {
				for (MoneyTransaction moneyTransaction : moneyTransactions) {
					session.save(moneyTransaction);
				}
			}
			tx.commit();
		} catch (Exception e) {
			if (tx != null)
				tx.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	@SuppressWarnings("unchecked")
	public List<Payment> getConfirmedPayments() {

		Session session = HibernateUtil.getSession().openSession();
		List<Payment> payments = new ArrayList<Payment>();
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			payments = session.createQuery("from Payment P where P.status=1").list();
			tx.commit();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			session.close();
		}
		return payments;

	}

	public Payment getPaymentByCustomer(int customerId, int id, Date date, String customerType) {
		Session session = HibernateUtil.getSession().openSession();
		Payment payment = null;
		Transaction tr = null;
		try {
			tr = session.beginTransaction();

			payment = (Payment) session
					.createQuery(
							"From Payment P where P.fund.id=:fundid and P.customerId=:custId and P.customerType=:cusType and P.paymentType=:payType and P.status=1 and P.confDate=:date")
					.setParameter("fundid", id).setParameter("custId", customerId).setParameter("cusType", customerType).setParameter("payType", "R").setParameter("date", date)
					.uniqueResult();

			tr.commit();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			session.close();
		}
		return payment;
	}

	@SuppressWarnings("unchecked")
	public List<Payment> getPaymentRtgs(int fundId, Date date) {
		Session session = HibernateUtil.getSession().openSession();
		List<Payment> payments = new ArrayList<Payment>();
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			payments = session.createQuery("from Payment P where P.status=1 and P.fund.id=:fundid and P.confDate=:date").setParameter("fundid", fundId).setParameter("date", date)
					.list();
			tx.commit();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			session.close();
		}
		return payments;
	}

	@SuppressWarnings("unchecked")
	public List<Payment> getConfirmedPayByFundNDate(int fundid, Date parse) {
		Session session = HibernateUtil.getSession().openSession();
		List<Payment> payments = new ArrayList<Payment>();
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			payments = session.createQuery("from Payment P where P.status=1 and P.fund.id=:fundid and P.confDate=:date and P.paymentType=:type").setParameter("fundid", fundid)
					.setParameter("date", parse).setParameter("type", "R").list();
			tx.commit();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			session.close();
		}
		return payments;
	}
}
